﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class Monster : Character, IScriptedPrefab, IEditable, ICustomSerialization
{
    public bool detectorPenetrateWalls;
    public float detectorRadius = 5f;
    public Effect dieEffect;
    public List<DropSetting> dropSettings = new List<DropSetting>();
    public float hp;
    public float lookSpeed;
    public float mass;
    public float moveSpeed;
    public JObject weaponData;

    protected override void Awake()
    {
        base.Awake();
        Life component = base.GetComponent<Life>();
        if (component != null)
        {
            component.onDie += delegate {
                this.StartWaitForSeconds(5f, () => UnityEngine.Object.Destroy(base.gameObject));
                if (this.dieEffect != null)
                {
                    this.dieEffect.Spawn<Effect>(base.transform.position);
                }
                if (this.anim != null)
                {
                    this.anim.Play("Die");
                }
                if (NetworkUtility.isServer)
                {
                    foreach (DropSetting setting in this.dropSettings)
                    {
                        if (UnityEngine.Random.Range((float) 0f, (float) 1f) < setting.dropRate)
                        {
                            GameUtility.CreateObject(setting.itemName, base.transform.position + ((Vector3) (UnityEngine.Random.insideUnitSphere.SetY(0f) * 0.5f)));
                        }
                    }
                }
            };
        }
        if (base.model.LoadClip("Idle", true) != null)
        {
            base.model.enabled = false;
        }
        if (base.move != null)
        {
            base.model.LoadClip("Move", true);
        }
        if (component != null)
        {
            base.model.LoadClip("Die", false);
        }
        if (base.attack != null)
        {
            base.model.LoadClip("Attack", false);
        }
    }

    void ICustomSerialization.OnDeserialize(string dataString)
    {
        Data data = JsonUtility.FromJson<Data>(dataString);
        this.dropSettings = data.dropSettings;
    }

    string ICustomSerialization.OnSerialize()
    {
        Data data = new Data {
            dropSettings = this.dropSettings
        };
        return JsonUtility.ToJson(data);
    }

    void IEditable.OnEditorGUI()
    {
        this.OnEditorGUI();
    }

    private void InitAttack()
    {
        if ((this.weaponData != null) && (this.weaponData["type"] != null))
        {
            System.Type type = AssetManager.FindType(this.weaponData["type"].ToString());
            if ((type != null) && type.Is(typeof(Weapon)))
            {
                Attack attack = this.AddComponent<Attack>();
                this.AddComponent<AIAttack>();
                Weapon target = this.CreateChildGameObject("Weapon").AddComponent(type) as Weapon;
                try
                {
                    GameJsonUtility.FromJsonOverwrite(this.weaponData, target);
                }
                catch (Exception exception)
                {
                    object[] args = new object[] { base.name, exception };
                    Debug.LogErrorFormat("Failed to load monster weapon data '{0}' : {1}", args);
                }
                target.Pickup(this);
                target.maxDurability = 0f;
                target.targetTagMask.Add(GameTags.Player);
                target.targetTagMask.Add(GameTags.Untagged);
                target.targetLayerMask = (LayerMask) GameLayers.Character;
                attack.weapon = target;
                base.isInfinteEnergy = true;
                AITargetDetector orAddComponent = this.GetOrAddComponent<AITargetDetector>();
                orAddComponent.triggerRadius = this.detectorRadius;
                orAddComponent.tagMask.Add(GameTags.Player);
                orAddComponent.tagMask.Add(GameTags.Untagged);
                orAddComponent.layerMask = (LayerMask) GameLayers.Character;
                orAddComponent.penetrateWalls = this.detectorPenetrateWalls;
            }
        }
    }

    protected virtual void InitPrefab()
    {
        base.tag = GameTags.Monster;
        this.InitAttack();
        if (this.moveSpeed > 0f)
        {
            Rigidbody rigidbody = this.AddComponent<Rigidbody>();
            rigidbody.constraints = RigidbodyConstraints.FreezeRotation;
            rigidbody.mass = this.mass;
            base.gameObject.AddComponent<Move>().speed = this.moveSpeed;
            this.AddComponent<AIMove>();
        }
        if (this.lookSpeed > 0f)
        {
            Look look = this.AddComponent<Look>();
            this.AddComponent<AILook>();
            look.speed = this.lookSpeed;
        }
        if (this.hp > 0f)
        {
            Life life = this.AddComponent<Life>();
            life.maxHp = this.hp;
            life.hp = this.hp;
            CapsuleCollider collider = this.AddComponent<CapsuleCollider>();
            collider.radius = 0.5f;
            collider.center = (Vector3) (Vector3.up * 0.5f);
            collider.height = 1f;
        }
    }

    void IScriptedPrefab.InitPrefab()
    {
        this.InitPrefab();
    }

    public override void OnDeserialize(NetworkReader reader, bool initialState)
    {
        base.OnDeserialize(reader, initialState);
    }

    protected virtual void OnEditorGUI()
    {
        GameGUI.ListField<DropSetting>("掉落物品(物品名/机率)", this.dropSettings, delegate (int i) {
            if (this.dropSettings[i] == null)
            {
                this.dropSettings[i] = new DropSetting();
            }
            GUILayout.BeginHorizontal(new GUILayoutOption[0]);
            this.dropSettings[i].itemName = GameGUI.AssetNameField(this.dropSettings[i].itemName);
            this.dropSettings[i].dropRate = GameGUI.FloatField(this.dropSettings[i].dropRate, 0.1f);
            GUILayout.EndHorizontal();
        });
    }

    public override bool OnSerialize(NetworkWriter writer, bool forceAll)
    {
        bool flag;
        bool flag2 = base.OnSerialize(writer, forceAll);
        return (flag | flag2);
    }

    private void UNetVersion()
    {
    }

    protected virtual void Update()
    {
        if (this.anim != null)
        {
            if (base.isDied)
            {
                this.anim.Play("Die");
            }
            else if ((base.attack != null) && base.attack.isAttacking)
            {
                this.anim.Play("Attack");
            }
            else if (this.localVelocity.z > 0.01f)
            {
                this.anim.Play("Move");
            }
            else
            {
                this.anim.Play("Idle");
            }
        }
    }

    private FrameAnimator anim
    {
        get
        {
            return ((base.model == null) ? null : base.model.frameAnimator);
        }
    }

    private Vector3 localVelocity
    {
        get
        {
            return ((base.rb == null) ? Vector3.zero : base.transform.InverseTransformDirection(base.rb.velocity));
        }
    }

    [Serializable]
    public class Data
    {
        public List<Monster.DropSetting> dropSettings = new List<Monster.DropSetting>();
    }

    [Serializable]
    public class DropSetting
    {
        public float dropRate = 1f;
        public string itemName;
    }
}

